#include <stdlib.h>
#include <pthread.h>
#include "map.h"

void check(bool test) {
	if (!test)
		exit(1);
}

void *thread1(void*);
void *thread2(void*);
void *thread3(void*);
void *thread4(void*);

nbds::map<int, int> l;

int main() {
	pthread_t t1, t2, t3, t4;
	
	pthread_create(&t1, NULL, thread1, NULL);
	pthread_create(&t2, NULL, thread2, NULL);
	pthread_create(&t3, NULL, thread3, NULL);
	pthread_create(&t4, NULL, thread4, NULL);

	pthread_join(t2, NULL);
	pthread_join(t4, NULL);
	pthread_join(t1, NULL);
	pthread_join(t3, NULL);

	for (int i = 1; i <= 10; i++)
		check(l.get(i) == 2);

	exit(0);
}

void *thread1(void*) { 
	for (int i = 0; i < 5000; i++) {
		l.set(6, 2);
		for (volatile int i = 0; i < 10; i++) wait();
		l.add(7, 1);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.set(8, 2);
		for (volatile int i = 0; i < 100; i++) wait();
		l.add(9, 1);
		l.add(10, 1);
	}
}

void *thread2(void*) {
	for (int i = 0; i < 5000; i++) {
		l.set(1, 2);
		for (volatile int i = 0; i < 100; i++) wait();
		l.add(2, 1);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.set(3, 2);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.add(4, 1);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.set(5, 2);
	}
}

void *thread3(void*) {
	for (int i = 0; i < 5000; i++) {
		l.add(1, 1);
		for (volatile int i = 0; i < 100; i++) wait();
		l.set(2, 2);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.add(3, 1);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.set(4, 2);
		for (volatile int i = 0; i < 1000; i++) wait();
		l.add(5, 1);
	}
}

void *thread4(void*) {
	for (int i = 0; i < 5000; i++) {
		l.add(6, 1);
		for (volatile int i = 0; i < 10; i++) wait();
		l.set(7, 2);
		for (volatile int i = 0; i < 100000; i++) wait();
		l.add(8, 1);
		for (volatile int i = 0; i < 100; i++) wait();
		l.set(9, 2);
		l.set(10, 2);
	}
}

